package textPixelId;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Vector;

import preproc.Image;
import utils.Constants;
import utils.Coordinates;


/* 
 * detecting pixels that belong to text
 */
public class TextId {
	Vector<ClusterInfo> clusters;
	
	
	private int fill(int r, int c, int w, int h, int crt, int[][] m, int[][] I) {
		Queue<Coordinates> q = new LinkedList<Coordinates>();
		q.add(new Coordinates(r, c));
		int num=0;
		
		m[r][c] = crt;
		
		int rMin=1000, cMin=1000, rMax=0, cMax=0;
		while (q.size()>0) {
			Coordinates coord = q.poll();
			if (coord.r < rMin) rMin = coord.r;
			if (coord.r > rMax) rMax = coord.r;
			if (coord.c < cMin) cMin = coord.c;
			if (coord.c > cMax) cMax = coord.c;
			
			num++;
			r = coord.r;
			c = coord.c;
			int minR = Math.max(r-1, 0);
			int maxR = Math.min(r+1, h-1);
			int minW = Math.max(c-1, 0);
			int maxW = Math.min(c+1, w-1);
			for (int r0=minR; r0<=maxR; r0++) {
				for (int c0=minW; c0<=maxW; c0++) {
					if (m[r0][c0]==0 && (Math.abs(I[r0][c0]-I[r][c])<Constants.MAX_DIFF)) {
						q.add(new Coordinates(r0, c0));
						m[r0][c0] = crt;
					}
				}
			}
		}
		
		clusters.add(new ClusterInfo(rMin, cMin, rMax, cMax, crt, num));
		return num;
		
		
	}
	
	public void findGroups(Image img) {
		clusters = new Vector<ClusterInfo>();
		
		int w = img.getWidth();
		int h = img.getHeight();
		int[][] I = img.intensity;
		
		int[][] aux = new int[h][w];
		Vector<Integer> clusterSizes = new Vector<Integer>();
		// clustrSizes.get(i) = number of pixels in cluster i;
		
		int currentCluster = 1; 
		for (int r=0; r<h; r++) {
			for (int c=0; c<w; c++) {
				if (aux[r][c]==0 && I[r][c] < 255) {
					int num = fill(r, c, w, h, currentCluster, aux, I);
					clusterSizes.add(num);
					currentCluster++;
				}
			}
		}
		
		/*
		if (Constants.DEBUG) {
			for (int r=0; r<h; r++) {
				for (int c=0; c<w; c++) {
					I[r][c] = (255+aux[r][c]*73) %256;
				}
			}
			img.showGreyscale("flood fill");
		}
		*/
		
		// remove small clusters (set num_pixels = 0 first)
		for (int r=0; r<h; r++) {
			for (int c=0; c<w; c++) {
				int pos = aux[r][c]-1;
				if (pos>=0) {
					int num = clusterSizes.get(pos);
					int sz = (clusters.get(pos).c1 - clusters.get(pos).c0)
							* (clusters.get(pos).r1 - clusters.get(pos).r0);
					
					boolean textPixel = true;
					if (num==0) {
						textPixel = false;
					}
					if (num<Constants.MIN_CLUSTER_SIZE) {
						textPixel = false;
					}
					else if (num<sz*Constants.MIN_PIXEL_RATIO) {
						textPixel = false;
					}
					
					if (!textPixel) {
						I[r][c] = 255;
						clusters.get(pos).num_pixels = 0;
					}
				}
				currentCluster++;
			}
		}
		
		img.maxClusterIdx = clusters.size()+1;
		
		// remove clusters with 0 pixels
		Vector<ClusterInfo> auxClusters = new Vector<ClusterInfo>();
		for (ClusterInfo c: clusters) {
			if (c.num_pixels > 0) auxClusters.add(c);
		}
		clusters = auxClusters;
		
		
		Collections.sort(clusters);

		if (Constants.DEBUG) {
			img.showGreyscale("remove small clusters");
		}
		
		img.clustered = aux;
		img.clusters = clusters;
		

	}
	
	public void identifyText(Image img) {
		findGroups(img);
	}

}
